package appserver;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Hashtable;

public class TcpIPServer implements Runnable {
	private int numberOfClients;
	private ArrayList<Listener> listeners = new ArrayList<Listener>();
	private boolean lastClientDisconnected = false;
	private ServerSocket serverSocket;
	private boolean pingerStarted = false;
	private Properties properties;
	private QueueManager manager;
	
	public int getNumberOfClients() {
		return numberOfClients;
	}
	public TcpIPServer(String propertiesFilePath, QueueManager manager){
		properties = new Properties(propertiesFilePath);
		numberOfClients = 0;
		try{
			serverSocket = new ServerSocket(Integer.parseInt(properties.getProperty("port")));
			serverSocket.setSoTimeout(Integer.parseInt(properties.getProperty("timeout")));
		}
		catch (Exception e){
			e.printStackTrace();
		}
		this.manager = manager;
	}
	@Override
	public void run() {
		while(numberOfClients > 0 || !lastClientDisconnected)
		{
			try{
				Socket clientSocket = serverSocket.accept();
				numberOfClients++;
				boolean distributed = false;
				synchronized (listeners){
					if(!listeners.isEmpty()){
						for(Listener l: listeners){
							if(l.getNumberOfClients() < Integer.parseInt(properties.getProperty("clients_per_thread"))){
								l.addClient(clientSocket);
								distributed = true;
							}
						}
					}
					if (!distributed){
						Listener l = new Listener(this, clientSocket, listeners.size()+1, manager);
						listeners.add(l);
						manager.addListener(l);
						//pinger.addListener(l);
						new Thread(l).start();
					}
				}
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
		try {
				if(this.numberOfClients == 0){
				System.out.println("All clients disconnected.");
				System.out.println("Server is shutting down.");
				serverSocket.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	public void decreaseNumOfClients(){
		numberOfClients--;
		if(numberOfClients == 0)
			lastClientDisconnected = true;
	}
	public void removeListener(Listener l) {
		synchronized (listeners){
			listeners.remove(l);
		}
	}
}
